package com.ssy.lingxi.pay.serviceimpl;

import cn.hutool.core.date.DateUtil;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.pay.common.CommonBooleanEnum;
import com.ssy.lingxi.pay.common.CreditTradeOperationEnum;
import com.ssy.lingxi.pay.common.CreditTradeStatusEnum;
import com.ssy.lingxi.pay.entity.CreditTradeRecordDO;
import com.ssy.lingxi.pay.model.vo.request.PageQueryCreditTradeRecordVO;
import com.ssy.lingxi.pay.model.vo.response.CreditOverdueTradeRecordAppVO;
import com.ssy.lingxi.pay.model.vo.response.CreditOverdueTradeRecordVO;
import com.ssy.lingxi.pay.model.vo.response.CreditTradeRecordPageQueryAppVO;
import com.ssy.lingxi.pay.model.vo.response.CreditTradeRecordPageQueryVO;
import com.ssy.lingxi.pay.repository.CreditTradeRecordRepository;
import com.ssy.lingxi.pay.service.ICreditTradeRecordService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 授信交易记录接口实现
 * @author 伍将
 * @date 2020/8/21
 * @version 2.0.0
 */
@Service
public class CreditTradeRecordServiceImpl implements ICreditTradeRecordService {

    @Resource
    private CreditTradeRecordRepository recordRepository;

    /**
     * 分页查询授信交易记录
     * @author 伍将
     * @date 2020/8/21
     * @param pageVO:
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.pay.model.vo.response.CreditTradeRecordPageQueryVO>>
     **/
    @Override
    public Wrapper<PageData<CreditTradeRecordPageQueryVO>> pageTradeRecord(PageQueryCreditTradeRecordVO pageVO) {

        // step 1: 组装查询条件
        Specification<CreditTradeRecordDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("creditId").as(Long.class), pageVO.getCreditId()));
            list.add(criteriaBuilder.equal(root.get("billId").as(Long.class), pageVO.getBillId()));
            list.add(criteriaBuilder.equal(root.get("isTemp").as(Integer.class), CommonBooleanEnum.NO.getCode()));

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数（按审批时间顺序排序）
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("tradeTime").descending());

        // step 3: 分页查询数据
        Page<CreditTradeRecordDO> result = recordRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<CreditTradeRecordPageQueryVO> resultList = result.getContent().stream().map(r -> {
            CreditTradeRecordPageQueryVO queryVO = new CreditTradeRecordPageQueryVO();
            queryVO.setId(r.getId());
            queryVO.setTradeCode(r.getTradeCode());
            queryVO.setTradeTime(DateUtil.format(DateUtil.date(r.getTradeTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setTradeMoney(r.getTradeMoney());
            queryVO.setStatus(r.getStatus());
            queryVO.setStatusName(CreditTradeStatusEnum.getItemMessage(r.getStatus()));
            queryVO.setOperation(r.getOperation());
            queryVO.setOperationName(CreditTradeOperationEnum.getItemMessage(r.getOperation()));
            queryVO.setRemark(r.getRemark());
            queryVO.setPayProveList(r.getPayProveList());

            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 获取交易记录
     * @param billIdList: 账单id列表
     * @param operation: 交易项目: 1-订单支付, 2-订单退款, 3-
     * @param tradeStatus:交易状态
     * @return
     */
    @Override
    public Wrapper<List<CreditOverdueTradeRecordVO>> getTradeRecordList(List<Long> billIdList, Integer operation, Integer tradeStatus) {

        Specification<CreditTradeRecordDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("operation").as(Integer.class), operation));
            list.add(criteriaBuilder.equal(root.get("status").as(Integer.class), tradeStatus));
            // 账单id
            Expression<Integer> exp = root.get("billId").as(Integer.class);
            list.add(exp.in(billIdList));

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        List<CreditTradeRecordDO> result = recordRepository.findAll(spec);

        // step 4: 组装返回数据
        List<CreditOverdueTradeRecordVO> resultList = result.stream().map(r -> {
            CreditOverdueTradeRecordVO queryVO = new CreditOverdueTradeRecordVO();
            queryVO.setBillId(r.getBillId());
            queryVO.setTradeCode(r.getTradeCode());
            queryVO.setTradeTime(DateUtil.format(DateUtil.date(r.getTradeTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setTradeMoney(r.getTradeMoney());
            queryVO.setOperation(r.getOperation());
            queryVO.setPayProveList(r.getPayProveList());

            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(resultList);
    }

    /**
     * App端查询逾期交易记录
     * @param billIdList
     * @param operation
     * @param tradeStatus
     * @return
     */
    @Override
    public Wrapper<List<CreditOverdueTradeRecordAppVO>> getTradeRecordListByApp(List<Long> billIdList, Integer operation, Integer tradeStatus){

        Specification<CreditTradeRecordDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("operation").as(Integer.class), operation));
            list.add(criteriaBuilder.equal(root.get("status").as(Integer.class), tradeStatus));
            // 账单id
            Expression<Integer> exp = root.get("billId").as(Integer.class);
            list.add(exp.in(billIdList));

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        List<CreditTradeRecordDO> result = recordRepository.findAll(spec);

        // step 4: 组装返回数据
        List<CreditOverdueTradeRecordAppVO> resultList = result.stream().map(r -> {
            CreditOverdueTradeRecordAppVO queryVO = new CreditOverdueTradeRecordAppVO();
            queryVO.setBillId(r.getBillId());
            queryVO.setTradeCode(r.getTradeCode());
            queryVO.setTradeTime(r.getTradeTime());
            queryVO.setTradeMoney(r.getTradeMoney());
            queryVO.setStatus(r.getStatus());
            queryVO.setStatusName(CreditTradeStatusEnum.getItemMessage(r.getStatus()));
            queryVO.setOperation(r.getOperation());
            queryVO.setPayProveList(r.getPayProveList());

            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(resultList);
    }

    /**
     * App端分页查询授信交易记录
     * @author 伍将
     * @date 2021/3/5
     * @param pageVO: 请求参数
     * @return 操作结果
     **/
    @Override
    public Wrapper<PageData<CreditTradeRecordPageQueryAppVO>> pageTradeRecordByApp(PageQueryCreditTradeRecordVO pageVO) {
        // step 1: 组装查询条件
        Specification<CreditTradeRecordDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("creditId").as(Long.class), pageVO.getCreditId()));
            list.add(criteriaBuilder.equal(root.get("billId").as(Long.class), pageVO.getBillId()));
            list.add(criteriaBuilder.equal(root.get("isTemp").as(Integer.class), CommonBooleanEnum.NO.getCode()));

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数（按审批时间顺序排序）
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("tradeTime").descending());

        // step 3: 分页查询数据
        Page<CreditTradeRecordDO> result = recordRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<CreditTradeRecordPageQueryAppVO> resultList = result.getContent().stream().map(r -> {
            CreditTradeRecordPageQueryAppVO queryVO = new CreditTradeRecordPageQueryAppVO();
            queryVO.setId(r.getId());
            queryVO.setTradeCode(r.getTradeCode());
            queryVO.setTradeTime(r.getTradeTime());
            queryVO.setTradeMoney(r.getTradeMoney());
            queryVO.setStatus(r.getStatus());
            queryVO.setStatusName(CreditTradeStatusEnum.getItemMessage(r.getStatus()));
            queryVO.setOperation(r.getOperation());
            queryVO.setOperationName(CreditTradeOperationEnum.getItemMessage(r.getOperation()));
            queryVO.setRemark(r.getRemark());
            queryVO.setPayProveList(r.getPayProveList());

            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }
}
